<script lang="tsx" setup>
import { computed, defineAsyncComponent, ref } from 'vue';

import { usePreferences } from '@vben/preferences';

// Get theme state
const { isDark } = usePreferences();
interface Component {
  name: string;
  path: string;
  description: string;
  category?: string;
}
// Define component list
const components = ref<Component[]>([
  {
    name: 'Accordion',
    path: 'Accordion',
    description: 'Display collapsible content sections',
    category: 'Layout',
  },
  {
    name: 'Avatar',
    path: 'Avatar',
    description: 'Display user or item images, initials, or icons',
    category: 'Display',
  },
  {
    name: 'Button',
    path: 'Button',
    description: 'Trigger an action or event',
    category: 'Inputs',
  },
  {
    name: 'CheckBox',
    path: 'CheckBox',
    description: 'Allow selection of multiple items from a list',
    category: 'Inputs',
  },
  {
    name: 'Dialog',
    path: 'Dialog',
    description: 'Modal windows for important information',
    category: 'Feedback',
  },
  {
    name: 'Divider',
    path: 'Divider',
    description: 'Visual separator between content',
    category: 'Layout',
  },
  {
    name: 'Drawer',
    path: 'Drawer',
    description: 'Side panel for displaying content',
    category: 'Layout',
  },
  {
    name: 'Drawer',
    path: 'Drawer',
    description: 'Side panel for displaying content',
    category: 'Layout',
  },
  {
    name: 'Dropdown',
    path: 'Dropdown',
    description: 'Select a single value from a list of options',
    category: 'Inputs',
  },
  {
    name: 'Field',
    path: 'Field',
    description: 'Container for form elements with labels and messages',
    category: 'Inputs',
  },
  {
    name: 'Label',
    path: 'Label',
    description: 'Add descriptive text to form controls',
    category: 'Display',
  },
  {
    name: 'Link',
    path: 'Link',
    description: 'Navigate between pages or resources',
    category: 'Navigation',
  },
  {
    name: 'ListBox',
    path: 'ListBox',
    description: 'List of selectable options',
    category: 'Display',
  },
  {
    name: 'Menu',
    path: 'Menu',
    description: 'Contextual menu with dropdown options',
    category: 'Navigation',
  },
  {
    name: 'ProgressBar',
    path: 'ProgressBar',
    description: 'Show the completion status of a task',
    category: 'Feedback',
  },
  {
    name: 'Radio',
    path: 'Radio',
    description: 'Allow selection of a single option from a list',
    category: 'Inputs',
  },
  {
    name: 'Slider',
    path: 'Slider',
    description: 'Select a value from a range',
    category: 'Inputs',
  },
  {
    name: 'Spinner',
    path: 'Spinner',
    description: 'Indicate content loading state',
    category: 'Feedback',
  },
  {
    name: 'Switch',
    path: 'Switch',
    description: 'Toggle between two states',
    category: 'Inputs',
  },
  {
    name: 'Tab',
    path: 'Tab',
    description: 'Organize content into separate views',
    category: 'Navigation',
  },
  {
    name: 'TextArea',
    path: 'TextArea',
    description: 'Multi-line text input field',
    category: 'Inputs',
  },
  {
    name: 'TextInput',
    path: 'TextInput',
    description: 'Single-line text input field',
    category: 'Inputs',
  },
  {
    name: 'ToggleButton',
    path: 'ToggleButton',
    description: 'Button that can be toggled on/off',
    category: 'Inputs',
  },
  {
    name: 'Tooltip',
    path: 'Tooltip',
    description: 'Show additional information on hover',
    category: 'Feedback',
  },
  {
    name: 'Tree',
    path: 'Tree',
    description: 'Display hierarchical data structures',
    category: 'Display',
  },
]);

// Search and filtering state
const searchQuery = ref('');
const currentCategory = ref('');
const selectedComponent = ref<Component | null>(null);
const loadError = ref<null | string>(null);

// Extract unique categories
const categories = computed(() => {
  const uniqueCategories = new Set<string>();
  components.value.forEach((comp) => {
    if (comp.category) {
      uniqueCategories.add(comp.category);
    }
  });
  return [...uniqueCategories].sort();
});

// Filter components based on search and category
const filteredComponents = computed(() => {
  return components.value.filter((component) => {
    const matchesSearch =
      component.name.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
      component.description
        .toLowerCase()
        .includes(searchQuery.value.toLowerCase());

    const matchesCategory =
      currentCategory.value === '' ||
      component.category === currentCategory.value;

    return matchesSearch && matchesCategory;
  });
});

// Function to create async component
const loadComponent = (path: string) => {
  try {
    return defineAsyncComponent({
      loader: async () => {
        const module = await import(`../ui_gallery/${path}Gallery.vue`);
        return module.default;
      },
      loadingComponent: () => (
        <div class="flex items-center justify-center p-8">
          <div class="flex items-center space-x-2">
            <div class="h-4 w-4 animate-spin rounded-full border-2 border-blue-500 border-t-transparent"></div>
            <span class={`${isDark.value ? 'text-gray-300' : 'text-gray-600'}`}>
              Loading component...
            </span>
          </div>
        </div>
      ),
      errorComponent: () => (
        <div
          class={`rounded-md p-4 ${
            isDark.value ? 'bg-red-900 text-red-300' : 'bg-red-50 text-red-500'
          }`}
        >
          Failed to load component
        </div>
      ),
      delay: 200,
      timeout: 3000,
    });
  } catch (error) {
    loadError.value = `Failed to load component: ${path} ${error}`;
    return null;
  }
};

// Select a component to preview
const selectComponent = (component: Component) => {
  selectedComponent.value = component;
  loadError.value = null;
};
</script>

<template>
  <div
    class="bg-background text-foreground relative min-h-screen w-full"
    :data-theme="isDark ? 'dark' : 'light'"
  >
    <div class="container mx-auto p-8">
      <h1 class="mb-6 text-2xl font-bold">Fluent UI Component Gallery</h1>

      <!-- Search bar -->
      <div class="mb-6">
        <div class="relative">
          <input
            v-model="searchQuery"
            type="text"
            placeholder="Search components..."
            class="w-full rounded-md border px-4 py-2 pr-10 focus:border-blue-500 focus:outline-none"
            :class="[
              isDark
                ? 'border-input bg-card text-foreground placeholder-muted-foreground'
                : 'border-input bg-card text-foreground placeholder-muted-foreground',
            ]"
          />
          <span
            class="material-icons text-muted-foreground absolute right-3 top-2"
          >
            search
          </span>
        </div>
      </div>

      <!-- Filter tabs -->
      <div class="mb-6">
        <div class="flex flex-wrap gap-2">
          <button
            @click="currentCategory = ''"
            class="rounded-full px-3 py-1 text-sm transition-colors"
            :class="[
              currentCategory === ''
                ? 'bg-primary text-primary-foreground'
                : isDark
                  ? 'bg-accent text-accent-foreground hover:bg-accent/80'
                  : 'bg-accent text-accent-foreground hover:bg-accent/80',
            ]"
          >
            All
          </button>
          <button
            v-for="category in categories"
            :key="category"
            @click="currentCategory = category"
            class="rounded-full px-3 py-1 text-sm transition-colors"
            :class="[
              currentCategory === category
                ? 'bg-blue-500 text-white'
                : isDark
                  ? 'bg-gray-700 text-gray-300 hover:bg-gray-600'
                  : 'bg-gray-100 text-gray-700 hover:bg-gray-200',
            ]"
          >
            {{ category }}
          </button>
        </div>
      </div>

      <!-- Components grid -->
      <div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
        <div
          v-for="component in filteredComponents"
          :key="component.name"
          class="cursor-pointer rounded-md border p-4 transition-colors"
          :class="[
            isDark
              ? 'border-border bg-card hover:border-primary hover:bg-accent'
              : 'border-border bg-card hover:border-primary hover:bg-accent',
          ]"
          @click="selectComponent(component)"
        >
          <h3 class="font-medium">{{ component.name }} Component</h3>
          <p class="text-muted-foreground mt-1 text-sm">
            {{ component.description }}
          </p>
        </div>
      </div>

      <!-- Component preview dialog -->
      <div
        v-if="selectedComponent"
        class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4"
      >
        <div
          class="bg-card relative max-h-[90vh] w-full max-w-4xl overflow-auto rounded-lg p-6"
        >
          <button
            @click="selectedComponent = null"
            class="text-muted-foreground hover:bg-accent hover:text-foreground absolute right-4 top-4 rounded-full p-1 transition-colors"
          >
            <span class="material-icons">close</span>
          </button>
          <component
            v-if="selectedComponent"
            :is="loadComponent(selectedComponent.path)"
          />

          <div
            v-if="loadError"
            class="mt-4 rounded-md p-4"
            :class="[
              isDark ? 'bg-red-900 text-red-300' : 'bg-red-50 text-red-500',
            ]"
          >
            Failed to load component: {{ loadError }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.container {
  max-width: 1200px;
}

/* Animation for the dialog */
.dialog-enter-active,
.dialog-leave-active {
  transition: opacity 0.3s;
}

.dialog-enter-from,
.dialog-leave-to {
  opacity: 0;
}
</style>
